﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using InkFx.WinControl.Core;
using InkFx.WinControl.Utils;
using Temp_20190910_AForm8.Dock;
using DA = InkFx.WinControl.XIDEAlignment;
using DTG = InkFx.WinControl.XIDETabGroup;
using DTGS = InkFx.WinControl.XIDETabGroupState;
using DTGP = InkFx.WinControl.XIDETabGroupPage;
using DTGPR = InkFx.WinControl.XIDETabGroupPageRect;
using DTGB = InkFx.WinControl.XIDETabGroupButton;

namespace InkFx.WinControl
{
    [ToolboxItem(false)]
    public class XIDETabGroup : UserControl
    {
        public XIDETabGroup(XIDEPanel idePanel, SplitterPanel parent, XIDEAlignment align)
        {
            //SetStyle(Win32API.ControlStylesUAORSD, true);
            this.m_IDEPanel = idePanel;
            this.m_Alignment = (align == XIDEAlignment.None) ? XIDEAlignment.Left : align;
            this.m_ParentSplitPanel = parent;
            if (idePanel != null) idePanel.RegTabGroup(this);
            base.BackColor = Color.Transparent;
            base.Dock = DockStyle.Fill;
            base.DoubleBuffered = true;
            //base.BorderStyle = BorderStyle.FixedSingle;
        }

        #region  事件

        protected static readonly object m_EventCloseClick = new object();
        protected static readonly object m_EventRivetClick = new object();
        protected static readonly object m_EventNormalClick = new object();
        protected static readonly object m_EventMaximizeClick = new object();
        protected static readonly object m_EventMenuStripClick = new object();
        protected static readonly object m_EventStateChanged = new object();

        public event XIDEPageEventHandler CloseClick
        {
            add { base.Events.AddHandler(m_EventCloseClick, value); }
            remove { base.Events.RemoveHandler(m_EventCloseClick, value); }
        }
        public event EventHandler RivetClick
        {
            add { base.Events.AddHandler(m_EventRivetClick, value); }
            remove { base.Events.RemoveHandler(m_EventRivetClick, value); }
        }
        public event EventHandler StateChanged
        {
            add { base.Events.AddHandler(m_EventStateChanged, value); }
            remove { base.Events.RemoveHandler(m_EventStateChanged, value); }
        }
        
        #endregion

        #region 字段属性

        protected XIDEPanel m_IDEPanel;
        protected XIDEAlignment m_Alignment = XIDEAlignment.Left;
        protected XIDETabGroupState m_State = XIDETabGroupState.Expand;
        protected XIDETabGroupPage m_SelectedPage = null;
        protected List<XIDETabGroupPage> m_ListPage = new List<XIDETabGroupPage>();

        public virtual XIDEAlignment Alignment
        {
            get { return m_Alignment; }
            set
            {
                if (m_Alignment == value) return;
                m_Alignment = value;
                if (m_Alignment == DA.Center && m_State == DTGS.Collapse) State = DTGS.Expand;
            }
        }
        public XIDEPanel IDEPanel
        {
            get { return m_IDEPanel; }
        }

        public virtual DTGS State
        {
            get { return m_State; }
            set
            {
                if (m_State == value) return;
                if (Alignment == DA.Center && value == DTGS.Collapse) { return; }
                SetState(value);
                //IDEPopPanel.TogglePopGroup(null);
            }
        }
        public XIDETabGroupPage PopupPage { get; set; }
        public List<XIDETabGroupPage> ListPage
        {
            get { return m_ListPage; }
        }

        public bool InCenterPanel
        {
            get
            {
                var idePanel = this.IDEPanel;
                if (idePanel == null) return false;
                var parent = this.Parent;
                do
                {
                    if (parent == idePanel.CenterPanel) return true;
                    parent = parent.Parent;
                } while (parent != null);

                return false;
            }
        }


        public override string Text
        {
            get
            {
                var page = this.SelectedPage;
                return page == null ? "" : page.Text;
            }
        }
        public XIDETabGroupPage SelectedPage
        {
            get
            {
                if (m_SelectedPage != null)
                {
                    if (m_ListPage.Contains(m_SelectedPage)) { return m_SelectedPage; }
                    else m_SelectedPage = null;
                }
                return m_ListPage.Count >= 1 ? m_ListPage[0] : null;
            }
        }
        public XIDEFrame SelectedControl
        {
            get
            {
                var page = this.SelectedPage;
                return page == null ? null : page.Control;
            }
        }


        #endregion




        public const int CAPTION_HEIGHT = 23;
        public const int CAPTION_BTN_SIZE = 17;



        #region  坐标区域


        protected Rectangle m_RectTitle = Rectangle.Empty;
        protected Rectangle m_RectText = Rectangle.Empty;
        protected Rectangle m_RectClose = Rectangle.Empty;
        protected Rectangle m_RectRivet = Rectangle.Empty;
        protected Rectangle m_RectMinMax = Rectangle.Empty;
        protected Rectangle m_RectMenuStrip = Rectangle.Empty;
        protected Rectangle m_RectFullTabPage = Rectangle.Empty;

        public virtual Rectangle RectTitle
        {
            get { return m_RectTitle; }
        }
        public virtual Rectangle RectText
        {
            get { return m_RectText; }
        }
        public virtual Rectangle RectClose
        {
            get { return m_RectClose; }
        }
        public virtual Rectangle RectRivet
        {
            get { return m_RectRivet; }
        }
        public virtual Rectangle RectMinMax
        {
            get { return m_RectMinMax; }
        }
        public virtual Rectangle RectMenuStrip
        {
            get { return m_RectMenuStrip; }
        }
        public virtual Rectangle RectFullTabPage
        {
            get { return m_RectFullTabPage; }
        }


        public void ResetRect()
        {
            if (this.Alignment == XIDEAlignment.Center)
                ResetCenterRect();
            else
                ResetNoCenterRect();
        }
        public virtual void ResetCenterRect()
        {
            int T = this.BorderColor == Color.Transparent ? 0 : 1;
            int pageCount = m_ListPage == null ? 0 : m_ListPage.Count;

            var rectTitle = new Rectangle(T, T, this.Width - T - T, CAPTION_HEIGHT);
            m_RectTitle = Rectangle.Empty;
            m_RectText = Rectangle.Empty;
            m_RectClose = Rectangle.Empty;
            m_RectRivet = Rectangle.Empty;
            m_RectMinMax = Rectangle.Empty;
            m_RectMenuStrip = new Rectangle(rectTitle.Width - CAPTION_BTN_SIZE - (rectTitle.Height - CAPTION_BTN_SIZE) / 2, rectTitle.Y + (rectTitle.Height - CAPTION_BTN_SIZE) / 2, CAPTION_BTN_SIZE, CAPTION_BTN_SIZE);
            m_RectFullTabPage = new Rectangle(rectTitle.X, rectTitle.Y, rectTitle.Width, CAPTION_HEIGHT); //new Rectangle(0, 0, rectTitle.Width - 3 - m_RectMenuStrip.Width - 3, CAPTION_HEIGHT);
            var padding = new Padding(T, m_RectFullTabPage.Height + T, T, T);
            base.Padding = padding;


            int maxWidth = m_RectFullTabPage.Width - (3 + m_RectMenuStrip.Width + 3);
            if (m_ListPage != null)
            {
                #region  计算各个子Page的标题区域

                int fullWidth = 0;
                foreach (var page in m_ListPage) { fullWidth = fullWidth + page.FullWidth; }

                int x = m_RectFullTabPage.X;
                for (int i = 0, len = m_ListPage.Count; i < len; i++)
                {
                    var page = m_ListPage[i];
                    if (x + page.FullWidth <= maxWidth)
                    {
                        page.RectRealTitle = new Rectangle(x, m_RectFullTabPage.Y, page.FullWidth, m_RectFullTabPage.Height);
                    }
                    else
                    {
                        page.RectRealTitle = (i == 0) ? new Rectangle(x, m_RectFullTabPage.Y, maxWidth, m_RectFullTabPage.Height) : Rectangle.Empty;
                    }
                    x = x + page.FullWidth;
                }

                #endregion
            }
        }
        public virtual void ResetNoCenterRect()
        {
            int T = this.BorderColor == Color.Transparent ? 0 : 1;
            int pageCount = m_ListPage == null ? 0 : m_ListPage.Count;

            bool showTabPage = !(this.State == DTGS.Popup && this.PopupPage != null) && pageCount >= 2;
            m_RectTitle = new Rectangle(T, T, this.Width - T - T, CAPTION_HEIGHT);
            m_RectClose = new Rectangle(m_RectTitle.Width - CAPTION_BTN_SIZE - (m_RectTitle.Height - CAPTION_BTN_SIZE) / 2, m_RectTitle.Y + (m_RectTitle.Height - CAPTION_BTN_SIZE) / 2, CAPTION_BTN_SIZE, CAPTION_BTN_SIZE);
            m_RectRivet = (Alignment == DA.Center) ? Rectangle.Empty : new Rectangle(m_RectClose.X - 1 - m_RectClose.Width, m_RectClose.Y, m_RectClose.Width, m_RectClose.Height);
            m_RectMenuStrip = (Alignment == DA.Center) ? Rectangle.Empty : new Rectangle(m_RectRivet.X - 1 - m_RectRivet.Width, m_RectRivet.Y, m_RectRivet.Width, m_RectRivet.Height);
            m_RectText = new Rectangle(m_RectTitle.X + 3, m_RectTitle.Y, (Math.Min(Math.Min(m_RectMenuStrip.X, m_RectRivet.X), m_RectClose.X) - m_RectTitle.X - 3), m_RectTitle.Height);
            m_RectFullTabPage = (!showTabPage) ? Rectangle.Empty : new Rectangle(T, this.Height - CAPTION_HEIGHT - T, this.Width - T - T, CAPTION_HEIGHT);
            base.Padding = new Padding(T, m_RectTitle.Height + m_RectTitle.Y, T, m_RectFullTabPage.Height + T);

            var floatForm = this.FindForm() as XIDEFloatForm;
            if (floatForm != null) { m_RectMinMax = m_RectRivet; m_RectRivet = Rectangle.Empty; }


            if (showTabPage && m_ListPage != null)
            {
                #region  计算各个子Page的标题区域

                int fullWidth = 0;
                int maxWidth = m_RectFullTabPage.Width;
                foreach (var page in m_ListPage) fullWidth = fullWidth + page.FullWidth;

                if (maxWidth >= fullWidth)
                {
                    int x = m_RectFullTabPage.X;
                    for (int i = 0, len = m_ListPage.Count; i < len; i++)
                    {
                        var page = m_ListPage[i];
                        page.RectRealTitle = new Rectangle(x, m_RectFullTabPage.Y, page.FullWidth, m_RectFullTabPage.Height);
                        x = x + page.FullWidth;
                    }
                }
                else
                {
                    int x = m_RectFullTabPage.X;
                    int width1 = maxWidth / m_ListPage.Count;
                    int width2 = width1 + maxWidth - (width1 * m_ListPage.Count);
                    for (int i = 0, len = m_ListPage.Count; i < len; i++)
                    {
                        var page = m_ListPage[i];
                        var width3 = (i >= len - 1) ? width2 : width1;
                        page.RectRealTitle = (i >= len - 1)
                            ? new Rectangle(x, m_RectFullTabPage.Y, width2, m_RectFullTabPage.Height)
                            : new Rectangle(x, m_RectFullTabPage.Y, width1, m_RectFullTabPage.Height);
                        x = x + width3;
                    }
                }

                #endregion
            }
            else if (m_ListPage != null)
            {
                #region  将各个子Page的标题区域 置为无效

                for (int i = 0, len = m_ListPage.Count; i < len; i++)
                {
                    var page = m_ListPage[i];
                    page.RectRealTitle = Rectangle.Empty;
                }

                #endregion
            }
        }

        #endregion


        #region  核心行为

        public void SetState(XIDETabGroupState state)
        {
            if (m_State == state) return;
            if (Alignment == DA.Center && (state == DTGS.Collapse || state == DTGS.Popup))
                throw new Exception("中央布局的控件不允许设置为 折叠或弹出 状态!");

            var oldState = m_State;
            m_State = state;

            bool dock = (oldState == DTGS.Expand || oldState == DTGS.Collapse);
            
            if (m_State == DTGS.Expand || m_State == DTGS.Collapse)
            {
                if (!dock) { this.DisposeFloatForm(); }
                if (m_State == DTGS.Expand) { this.Parent = this.ParentSplitPanel; }
                else if (m_State == DTGS.Collapse) { this.Parent = null; }
            }


            OnStateChanged(EventArgs.Empty);
        }
        public XIDETabGroup DoDock(XIDETabGroup group, DA align)
        {
            if (group == null || align == DA.None) return this;
            group.ReleaseParent();

            #region  原区域拆分

            var ctrl1 = this;
            //if (!(ctrl1 is IDETabGroup)) throw new Exception(string.Format("只允许布局附着到 IDETabGroup 的控件下, 不允许附着到 类型为 '{0}' 的控件下!", ctrl1.GetType().FullName));
            //MessageBox.Show(ctrl.GetType().ToString() + " > " + ctrl1.GetType().ToString());

            if (align == XIDEAlignment.Center)
            {
                //MessageBox.Show("中央增加控件: \r\n" + group.GetType().ToString() + " > " + ctrl1.GetType().ToString());

                group.DisposeFloatForm();
                group.Alignment = ctrl1.Alignment;
                var ctrl0 = group;
                ctrl1.MergeTabGroup(ctrl0);
                group.State = DTGS.Expand;
                ctrl1.Focus();
                return ctrl1;
            }
            else
            {
                this.SuspendLayout();
                group.DisposeFloatForm();
                group.Alignment = ctrl1.Alignment;
                var ctrl0 = group;

                var parent = ctrl1.Parent;
                var splitCtrl = new XIDESplitControl(this.IDEPanel);
                splitCtrl.Dock = DockStyle.Fill;
                if (align == XIDEAlignment.Top || align == XIDEAlignment.Bottom)
                { splitCtrl.Orientation = Orientation.Horizontal; }
                if (align == XIDEAlignment.Right || align == XIDEAlignment.Bottom)
                { var temp = ctrl0; ctrl0 = ctrl1; ctrl1 = temp; }

                ctrl1.Parent = null;
                splitCtrl.Parent = parent;
                splitCtrl.Size = parent.Size;
                ctrl0.Parent = splitCtrl.Panel1;
                ctrl1.Parent = splitCtrl.Panel2;

                //if (ctrl0 is IDETabGroup) { ((IDETabGroup)ctrl0).Parent = splitCtrl.Panel1; }
                //if (ctrl0 is IDESplitControl) { ((IDESplitControl)ctrl0).Parent = splitCtrl.Panel1; }
                //else { ctrl0.Parent = splitCtrl.Panel1; }

                //if (ctrl1 is IDETabGroup) { ((IDETabGroup)ctrl1).Parent = splitCtrl.Panel2; }
                //if (ctrl1 is IDESplitControl) { ((IDESplitControl)ctrl1).Parent = splitCtrl.Panel2; }
                //else { ctrl1.Parent = splitCtrl.Panel2; }

                group.State = DTGS.Expand;
                this.ResumeLayout();
                group.Focus();
                return group;
            }

            #endregion

            return this;
        }
        public XIDETabGroup DoDock(XIDEFrame ctrl, DA align)
        {
            if (ctrl == null || align == DA.None) return this;

            XIDETabGroup group = new XIDETabGroup(this.IDEPanel, null, align);
            ctrl.Dock = DockStyle.Fill;
            group.AppendTabPage(ctrl);
            return DoDock(group, align);
        }


        public void MergeTabGroup(XIDETabGroup group)
        {
            group.ReleaseParent();
            var list = new List<XIDETabGroupPage>(group.m_ListPage);
            for (int i = list.Count - 1; i >= 0; i--) { var page = list[i]; AppendTabPage(page, 0, false); }
            group.Dispose();
            SetSelectedPage(list[0]);
            this.ResetRect();
            this.Invalidate();
        }
        public XIDETabGroup SeparateTabGroup(XIDETabGroupPage page)
        {
            var idePanel = this.IDEPanel;
            XIDEPopPanel.TogglePopGroup(null);


            #region  可行的代码

            bool suspend = idePanel.SuspendLayout();

            //下面的代码, 执行分离时, 留在原地的是新建的 Group, 而原Group作为被拖出的部分 —— 这种做法可以规避焦点问题
            var list2 = new List<XIDETabGroupPage>(this.m_ListPage);
            list2.Remove(page);

            
            XIDETabGroup group = (list2.Count <= 0) ? null : new XIDETabGroup(this.IDEPanel, this.ParentSplitPanel, this.Alignment);
            if (group != null) { group.State = this.State; group.Parent = this.Parent; }
            this.Parent = null;
            if (this.Alignment == DA.Center) { this.Alignment = DA.FloatCenter; }
            this.State = DTGS.Float;


            foreach (var page2 in list2)
            {
                this.RemoveTabPage(page2, true);
                if (group != null) { group.AppendTabPage(page2, true); }
            }

            this.ResetRect(); this.Invalidate();
            if (group != null) { group.ResetRect(); group.Invalidate(); }

            if (suspend) idePanel.ResumeLayout();

            return this;

            #endregion


            #region  作废的代码

            //下面的代码, 执行分离时, 拖出的是 新建的 Group —— 这会导致 焦点问题
            //IDETabGroup group = new IDETabGroup(this.IDEPanel, this.ParentSplitPanel, this.Alignment);
            //this.RemoveTabPage(page);
            //group.AppendTabPage(page);
            //return group;

            #endregion
        }






        public void ClearPages()
        {
            var list = new List<XIDETabGroupPage>(m_ListPage);
            foreach (var page in list) { RemoveTabPage(page, false); }
            this.ResetRect(); this.Invalidate(); 
        }
        public XIDETabGroupPage FindTabPage(XIDEFrame ctrl)
        {
            var find = m_ListPage.FindAll(x => x.Control == ctrl);
            if (find.Count <= 0) return null;
            if (find.Count == 1) return find[0];
            if (find.Count >= 2)
            {
                foreach (var page in find) { RemoveTabPage(page, false); }
                AppendTabPage(find[0]);
                return find[0];
            }
            return null;
        }
        public void AppendTabPage(XIDEFrame ctrl)
        {
            RemoveTabPage(ctrl);
            XIDETabGroupPage page = new XIDETabGroupPage();
            page.Control = ctrl;
            AppendTabPage(page);
        }
        public void AppendTabPage(XIDETabGroupPage page)
        {
            AppendTabPage(page, true);
        }
        public void RemoveTabPage(XIDEFrame ctrl)
        {
            if (ctrl == null) return;
            var page = FindTabPage(ctrl);
            if (page != null) { RemoveTabPage(page, true); }
        }
        public void RemoveTabPage(XIDETabGroupPage page)
        {
            RemoveTabPage(page, true);
        }

        protected virtual void AppendTabPage(XIDETabGroupPage page, bool refresh)
        {
            AppendTabPage(page, -1, refresh);
        }
        protected virtual void AppendTabPage(XIDETabGroupPage page, int index, bool refresh)
        {
            if (page == null || page.Control == null) return;

            if (page.ParentGroup != null) { page.ParentGroup.RemoveTabPage(page, true); }

            page.ParentGroup = this;
            if (index >= 0 && index < m_ListPage.Count) this.m_ListPage.Insert(index, page);
            else this.m_ListPage.Add(page);
            page.Control.Parent = this;  //这行代码放到最后

            if (refresh) { this.ResetRect(); this.Invalidate(); }
        }
        protected virtual void RemoveTabPage(XIDETabGroupPage page, bool refresh)
        {
            if (page == null || !m_ListPage.Contains(page)) return;

            page.ParentGroup = null;
            if (page.Control != null) { page.Control.Parent = null; }
            m_ListPage.Remove(page); //这行代码放到最后

            if (m_ListPage.Count <= 0) { this.Dispose(); }
            else if (refresh && !this.Disposing && !this.IsDisposed) { this.ResetRect(); this.Invalidate(); }
        }

        public void SetSelectedPage(XIDETabGroupPage page)
        {
            if (!m_ListPage.Contains(page)) return;

            m_SelectedPage = page;
            page.Control.BringToFront();
            page.Control.Visible = true;
            this.ResetRect();
            this.Invalidate();
        }
        public void SetSelectedFirstPage(XIDETabGroupPage page)
        {
            if (!m_ListPage.Contains(page)) return;
            m_ListPage.Remove(page);
            m_ListPage.Insert(0, page);
            SetSelectedPage(page);
        }

        public DTGP FindTitlePageByPoint(Point point)
        {
            foreach (var page in m_ListPage)
            {
                if (page.RectRealTitle.Contains(point)) return page;
            }
            return null;
        }
        public DTGP FindClosePageByPoint(Point point)
        {
            if (this.Alignment == DA.Center)
            {
                foreach (var page in m_ListPage)
                {
                    if (page.RectRealClose.Contains(point)) return page;
                }
            }
            else
            {
                if (RectClose.Contains(point)) return SelectedPage;
            }
            return null;
        }

        protected virtual void OnCloseClick(XIDEPageEventArgs e)
        {
            XIDEPageEventHandler handler = base.Events[m_EventCloseClick] as XIDEPageEventHandler;
            if (handler != null) handler(this, e);
            this.DoClose(e.Page);
        }
        protected virtual void OnMenuStripClick(XIDEMenuStripEventArgs e)
        {
            XIDEMenuStripEventHandler handler = base.Events[m_EventMenuStripClick] as XIDEMenuStripEventHandler;
            if (handler != null) handler(this, e);
            this.DoMenuStrip(e.Group, e.Page, e.RightButton);
        }
        protected virtual void OnRivetClick(EventArgs e)
        {
            EventHandler handler = base.Events[m_EventRivetClick] as EventHandler;
            if (handler != null) handler(this, e);
            this.DoRivet();
        }
        protected virtual void OnNormalClick(EventArgs e)
        {
            EventHandler handler = base.Events[m_EventNormalClick] as EventHandler;
            if (handler != null) handler(this, e);
            this.DoNormal();
        }
        protected virtual void OnMaximizeClick(EventArgs e)
        {
            EventHandler handler = base.Events[m_EventMaximizeClick] as EventHandler;
            if (handler != null) handler(this, e);
            this.DoMaximize();
        }
        protected virtual void OnStateChanged(EventArgs e)
        {
            EventHandler handler = base.Events[m_EventStateChanged] as EventHandler;
            if (handler != null) handler(this, e);
            this.DoStateChanged();
        }

        #endregion




        protected SplitterPanel m_ParentSplitPanel;
        public SplitterPanel ParentSplitPanel
        {
            get { return m_ParentSplitPanel; }
        }
        public XIDESplitControl ParentSplitControl
        {
            get
            {
                var parent = this.ParentSplitPanel;
                var splitCtrl = XIDESplitControl.FindContainer(parent);
                return splitCtrl;
            }
        }





        #region  继承改写


        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public virtual Color BorderColor
        {
            get { return m_BorderColor; }
            set
            {
                m_BorderColor = value;
                this.Invalidate();
            }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        public new Padding Padding
        {
            get { return base.Padding; }
        }
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), Localizable(false)]
        protected override Padding DefaultPadding
        {
            get { return new Padding(1, CAPTION_HEIGHT + 1, 1, 1); }
        }
        [Obsolete("IDETabGroup禁止直接使用 Controls 属性添加子控件, 请使用 AppendTabPage(*) 函数执行此操作", true)]
        public new ControlCollection Controls
        {
            get { return base.Controls; }
        }

        //public new System.Windows.Forms.Control Parent
        //{
        //    get { return base.Parent; }
        //    set
        //    {
        //        if (base.Parent == value) return;

        //        var old = base.Parent;
        //        if (old != null) old.Controls.Remove(this);
        //        if (old != null && old.Controls.Contains(this))
        //            throw new Exception(string.Format("当代码设置 Parent 移除 IDETabGroup 后, Parent 的 Controls 依然包含此 IDETabGroup (这可能是 .Net 底层 WinForm 的 BUG) : \r\n    Parent = {0} \r\n    IDETabGroup = {1}", old, this));

        //        base.Parent = value;
        //    }
        //}


        public new void Focus()
        {
            if (!this.IsHandleCreated || this.Disposing || this.IsDisposed) return;
            base.Focus(); 
        }
        public new void Invalidate()
        {
            if (this.Disposing || this.IsDisposed) return;
            var size = this.Size;
            var padding = this.Padding;
            base.Invalidate(new Rectangle(0, 0, size.Width, padding.Top));
            base.Invalidate(new Rectangle(0, size.Height - padding.Bottom, size.Width, padding.Bottom));
            base.Invalidate(new Rectangle(0, 0, padding.Left, size.Height));
            base.Invalidate(new Rectangle(size.Width - padding.Right, 0, size.Width, size.Height));
            //base.Invalidate(false);
            //base.Invalidate();
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            ResetRect();
        }
        protected override void OnSizeChanged(EventArgs e)
        {
            base.OnSizeChanged(e);
            if (this.Disposing || this.IsDisposed) return;

            this.ResetRect();
            this.Invalidate();
        }


        protected override void OnMouseMove(MouseEventArgs e)
        {
            //Console.WriteLine("IDETabGroup OnMouseMove(MouseEventArgs e) : " + e.Location);
            base.OnMouseMove(e);
            if (this.Disposing || this.IsDisposed) return;

            var floatForm = this.FindForm() as XIDEFloatForm;
            bool diff = (floatForm != null && floatForm.WindowState == FormWindowState.Normal) || (Math.Abs(m_DragTitlePoint.X - e.X) >= 10 || Math.Abs(m_DragTitlePoint.Y - e.Y) >= 10);
            if (e.Button == MouseButtons.Left && diff) this.MoveFloat(e.Location);
            this.Invalidate();
        }
        protected override void OnMouseDown(MouseEventArgs e)
        {
            //Console.WriteLine("IDETabGroup OnMouseDown(MouseEventArgs e) : " + e.Location);
            base.OnMouseDown(e);
            if (this.Disposing || this.IsDisposed) return;
            
            DisposeOtherPopGroup();

            var page = FindClosePageByPoint(e.Location);
            if (page == null && e.Button == MouseButtons.Left) { this.StartFloat(e.Location); }
            this.Invalidate();
        }
        protected override void OnMouseUp(MouseEventArgs e)
        {
            //Console.WriteLine("IDETabGroup OnMouseUp(MouseEventArgs e) : " + e.Location);
            base.OnMouseUp(e);
            if (this.Disposing || this.IsDisposed) return;

            var page = FindClosePageByPoint(e.Location);
            if (page != null) { this.SetSelectedPage(page); }
            else if (e.Button == MouseButtons.Left) { this.EndFloat(e.Location); }
            this.Invalidate();
        }
        protected override void OnMouseEnter(EventArgs e)
        {
            base.OnMouseEnter(e);
            if (this.Disposing || this.IsDisposed) return;
            
            this.Invalidate();
            //Console.WriteLine("OnMouseEnter(EventArgs e)");
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            base.OnMouseLeave(e);
            if (this.Disposing || this.IsDisposed) return;
            
            this.Invalidate();
            //Console.WriteLine("OnMouseLeave(EventArgs e)");
        }
        protected override void OnMouseClick(MouseEventArgs e)
        {
            base.OnClick(e);
            if (this.Disposing || this.IsDisposed) return;

            Point point1 = MousePosition;
            Point point2 = this.PointToClient(point1);
            var closePage = FindClosePageByPoint(point2);

            if (closePage != null) { OnCloseClick(new XIDEPageEventArgs(closePage)); }
            else if (RectRivet.Contains(point2)) OnRivetClick(new XIDEPageEventArgs(this.SelectedPage));
            else if (RectMinMax.Contains(point2))
            {
                var floatForm = this.FindForm() as XIDEFloatForm;
                if (floatForm != null && floatForm.WindowState == FormWindowState.Normal) OnMaximizeClick(EventArgs.Empty);
                else if (floatForm != null && floatForm.WindowState == FormWindowState.Maximized) OnNormalClick(EventArgs.Empty);
            }
            else
            {
                DTGP pointPage = null;
                var list = new List<DTGP>(m_ListPage);
                foreach (var page in list)
                {
                    if (page.RectRealTitle.Contains(point2))
                    {
                        pointPage = page;
                        this.SetSelectedPage(page);
                    }
                }

                bool isRightButton = e.Button == MouseButtons.Right;
                if (isRightButton || RectMenuStrip.Contains(point2)) OnMenuStripClick(new XIDEMenuStripEventArgs(this, pointPage, isRightButton));
            }

        }
        protected override void OnMouseDoubleClick(MouseEventArgs e)
        {
            base.OnMouseDoubleClick(e);
            if (this.Disposing || this.IsDisposed) return;

            if (RectTitle.Contains(e.Location))
            {
                var floatForm = this.FindForm() as XIDEFloatForm;
                if (floatForm != null && floatForm.WindowState == FormWindowState.Normal) { floatForm.WindowState = FormWindowState.Maximized; }
                else if (floatForm != null && floatForm.WindowState == FormWindowState.Maximized) { floatForm.WindowState = FormWindowState.Normal; }
            }
        }
        protected override void OnEnter(EventArgs e)
        {
            base.OnEnter(e);
            if (this.Disposing || this.IsDisposed) return;
            
            this.IDEPanel.ActiveTabGroup = this;
            DisposeOtherPopGroup();
        }
        protected override void OnLeave(EventArgs e)
        {
            base.OnLeave(e);
            if (this.Disposing || this.IsDisposed) return;
            
            //处理了 OnEnter(EventArgs e) 后, 不要再处理 OnLeave(EventArgs e) —— 容易导致消息死循环, 这种BUG调试都调不出来
            //if (this.IDEPanel.ActiveTabGroup == this) this.IDEPanel.ActiveTabGroup = null;
            //DisposeCurrentPopGroup();
        }
        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);
            if (this.Disposing || this.IsDisposed) return;

            if (this.Parent is XIDEPanel)
                throw new Exception(string.Format("IDETabGroup 不能是 IDEPanel 的子控件 [这是一个内部BUG]: 错误的 Group.Text = '{0}' ", this.Text));


            var panel = this.Parent as SplitterPanel;
            if (panel != null)
            {
                var old2 = ParentSplitControl;
                m_ParentSplitPanel = panel;
                if (old2 != null) { old2.DoLayout(); }
            }

            this.ResetRect();
            this.Invalidate();
        }
        protected override void OnControlAdded(ControlEventArgs e)
        {
            base.OnControlAdded(e);
            if (this.Disposing || this.IsDisposed) return;
            
            var ctrl = e.Control as XIDEFrame;
            if (ctrl == null) throw new Exception("只允许向 IDETabGroup 添加 IDEFrame 类型的子控件");

            var page = FindTabPage(ctrl);
            if (page == null) throw new Exception("IDETabGroup禁止直接使用 Controls属性 或 子控件的Parent属性 添加子控件, 请使用 AppendTabPage(*) 函数执行此操作");
        }
        protected override void OnControlRemoved(ControlEventArgs e)
        {
            base.OnControlRemoved(e);
            if (this.Disposing || this.IsDisposed) return;
            
            var ctrl = e.Control as XIDEFrame;
            if (ctrl == null) throw new Exception("只允许向 IDETabGroup 添加 IDEFrame 类型的子控件");

            var page = FindTabPage(ctrl);
            if (page == null) throw new Exception("IDETabGroup禁止直接使用 Controls属性 或 子控件的Parent属性 删除子控件, 请使用 RemoveTabPage(*) 函数执行此操作");
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            if (this.Disposing || this.IsDisposed) return;
            
            if (this.Alignment == XIDEAlignment.Center)
                DrawTabCenterGroup(e.Graphics);
            else
                DrawTabNoCenterGroup(e.Graphics);

            //var floatForm = FindForm() as IDEFloatForm;
            //if(floatForm!=null) 

            var color = this.BorderColor;
            if (color.A >= 1) { GraphicsHelper.DrawBorder(e.Graphics, color, this.ClientRectangle, true, true); }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                //if (this.Parent != null) { throw new Exception("IDETabGroup 在执行 Dispose() 时, 未提前将 Parent 属性置空"); this.Parent = null; }

                DisposeOtherPopGroup();     //关闭弹出面板
                //if (m_IDEPanel != null) { m_IDEPanel.m_ListTabGroup.Remove(this); }  //加上这行代码后, 主窗体点击 关闭 时, FormClosingEventArgs.Cancel 不知道为什么会等于 true
                this.Parent = null;
                
                
                this.m_IDEPanel = null;
                this.m_SelectedPage = null;
                this.m_ListPage.Clear();
            }

            base.Dispose(disposing);
        }


        #endregion

        #region  执行重绘

        protected virtual void DrawTabCenterGroup(Graphics g)
        {
            bool debug = false;

            if (debug)
            {
                #region  DEBUG 重绘模式

                g.FillRectangle(new SolidBrush(this.ContainsFocus ? Color.Red : Color.RosyBrown), RectTitle);

                Point point1 = MousePosition;
                Point point2 = this.PointToClient(point1);
                bool press = MouseButtons == MouseButtons.Left;
                Color colorClose = !RectClose.Contains(point2) ? Color.Coral : (press ? Color.Brown : Color.Chocolate);
                Color colorRivet = !RectRivet.Contains(point2) ? Color.LightGreen : (press ? Color.LimeGreen : Color.SeaGreen);
                Color colorMenu = !RectMenuStrip.Contains(point2) ? Color.LightPink : (press ? Color.HotPink : Color.DeepPink);

                g.FillRectangle(new SolidBrush(colorClose), RectClose);
                g.FillRectangle(new SolidBrush(colorRivet), RectRivet);
                g.FillRectangle(new SolidBrush(colorMenu), RectMenuStrip);


                foreach (var page in m_ListPage)
                {
                    var rect1 = page.RectRealTitle;
                    var rect2 = page.RectRealClose;

                    Color color = page.Control.BackColor;
                    Color colorPage = (rect1.Contains(point2)/* && !rect2.Contains(point2)*/) ? ((press && !rect2.Contains(point2)) ? ColorHelper.DarkDark(color) : ColorHelper.Light(color)) : color;
                    Color colorPageClose = rect2.Contains(point2) ? (press ? Color.Brown : Color.Chocolate) : Color.Coral;

                    g.FillRectangle(new SolidBrush(colorPage), rect1);
                    g.FillRectangle(new SolidBrush(colorPageClose), rect2);
                }

                #endregion
            }
            else
            {
                #region  正式重绘

                var state = this.State;
                g.FillRectangle(new SolidBrush(this.ContainsFocus ? m_FocusColor : m_TitleColor), RectTitle);

                Point point1 = MousePosition;
                Point point2 = this.PointToClient(point1);
                bool press = MouseButtons == MouseButtons.Left;
                Image imgClose = GetBtnImage(DTGB.Close, RectClose.Contains(point2), press);
                Image imgRivet = GetBtnImage((state == DTGS.Expand ? DTGB.Expand : DTGB.Collapse), RectRivet.Contains(point2), press);
                Image imgMenu = GetBtnImage(DTGB.Menu, RectMenuStrip.Contains(point2), press);

                g.DrawImage(imgClose, RectClose);
                g.DrawImage(imgRivet, RectRivet);
                g.DrawImage(imgMenu, RectMenuStrip);

                foreach (var page1 in m_ListPage)
                {
                    var rect1 = page1.RectRealTitle;
                    var rect2 = page1.RectRealClose;

                    bool focus = page1 == this.SelectedPage;
                    bool hover1 = page1.RectRealTitle.Contains(point2);
                    bool hover2 = page1.RectRealClose.Contains(point2);
                    Color colorPage = ((press && hover1 && !hover2) || focus) ? m_FocusColor : ((hover1 && !hover2) ? Color.FromArgb(100, m_FocusColor) : m_TitleColor);
                    Image imgPageCloseClose = GetBtnImage(XIDETabGroupButton.Close, rect2.Contains(point2), press);

                    GraphicsHelper.FillBack(g, rect1, colorPage, true);
                    GraphicsHelper.DrawImage(g, imgPageCloseClose, rect2);
                    GraphicsHelper.DrawImage(g, page1.Icon, page1.RectRealIcon);
                    GraphicsHelper.DrawStringMiddle(g, page1.Text, this.Font, this.ForeColor, page1.RectRealText, this.Enabled);
                }

                #endregion
            }


        }
        protected virtual void DrawTabNoCenterGroup(Graphics g)
        {
            bool debug = false;

            if (debug)
            {
                #region  DEBUG 重绘模式

                g.FillRectangle(new SolidBrush(this.ContainsFocus ? Color.Red : Color.RosyBrown), RectTitle);

                Point point1 = MousePosition;
                Point point2 = this.PointToClient(point1);
                bool press = MouseButtons == MouseButtons.Left;
                Color colorClose = !RectClose.Contains(point2) ? Color.Coral : (press ? Color.Brown : Color.Chocolate);
                Color colorRivet = !RectRivet.Contains(point2) ? Color.LightGreen : (press ? Color.LimeGreen : Color.SeaGreen);
                Color colorMenu = !RectMenuStrip.Contains(point2) ? Color.LightPink : (press ? Color.HotPink : Color.DeepPink);

                g.FillRectangle(new SolidBrush(colorClose), RectClose);
                g.FillRectangle(new SolidBrush(colorRivet), RectRivet);
                g.FillRectangle(new SolidBrush(colorMenu), RectMenuStrip);

                int pageCount = m_ListPage == null ? 0 : m_ListPage.Count;
                bool showTabPage = !(this.State == DTGS.Popup && this.PopupPage != null) && pageCount >= 2; ;
                if (showTabPage && m_ListPage != null)
                {
                    foreach (var page in m_ListPage)
                    {
                        Color color = page.Control.BackColor;
                        Color colorPage = !page.RectRealTitle.Contains(point2) ? color : (press ? ColorHelper.DarkDark(color) : ColorHelper.Light(color));
                        g.FillRectangle(new SolidBrush(colorPage), page.RectRealTitle);
                    }
                }

                #endregion
            }
            else
            {
                #region  正式重绘

                var state = this.State;
                var page = this.SelectedPage;
                var floatForm = FindForm() as XIDEFloatForm;
                g.FillRectangle(new SolidBrush(this.ContainsFocus ? m_FocusColor : m_TitleColor), RectTitle);

                Point point1 = MousePosition;
                Point point2 = this.PointToClient(point1);
                bool press = MouseButtons == MouseButtons.Left;
                Image imgClose = GetBtnImage(DTGB.Close, RectClose.Contains(point2), press);
                Image imgRivet = floatForm!=null? null: GetBtnImage((state == DTGS.Expand ? DTGB.Expand : DTGB.Collapse), RectRivet.Contains(point2), press);
                Image imgMinMax = floatForm == null ? null : GetBtnImage((floatForm.WindowState == FormWindowState.Normal ? DTGB.Maximize : DTGB.Normal), RectMinMax.Contains(point2), press);
                Image imgMenu = GetBtnImage(DTGB.Menu, RectMenuStrip.Contains(point2), press);

                g.DrawImage(imgClose, RectClose);
                g.DrawImage(imgMenu, RectMenuStrip);
                if (imgRivet != null) g.DrawImage(imgRivet, RectRivet);
                if (imgMinMax != null) g.DrawImage(imgMinMax, RectMinMax);
                
                if (page != null)
                {
                    //GraphicsHelper.DrawImage(g, page.Icon, page.RectRealIcon);
                    GraphicsHelper.DrawStringMiddle(g, page.Text, this.Font, this.ForeColor, RectText, this.Enabled);
                }


                int pageCount = m_ListPage == null ? 0 : m_ListPage.Count;
                bool showTabPage = !(this.State == DTGS.Popup && this.PopupPage != null) && pageCount >= 2; ;
                if (showTabPage && m_ListPage != null)
                {
                    foreach (var page1 in m_ListPage)
                    {
                        bool focus = page1 == this.SelectedPage;
                        bool hover = page1.RectRealTitle.Contains(point2);
                        Color colorPage = ((press && hover) || focus) ? m_FocusColor : (hover ? Color.FromArgb(100, m_FocusColor) : m_TitleColor);
                        GraphicsHelper.FillBack(g, page1.RectRealTitle, colorPage, true);
                        GraphicsHelper.DrawImage(g, page1.Icon, page1.RectRealIcon);
                        GraphicsHelper.DrawStringMiddle(g, page1.Text, this.Font, this.ForeColor, page1.RectRealText, this.Enabled);
                    }
                }

                #endregion
            }



        }

        private static Color m_TitleColor = Color.LightSteelBlue;
        private static Color m_FocusColor = Color.LightYellow;
        private static Color m_BorderColor = Color.FromArgb(100, 200, 200, 200);
        public static Image GetBtnImage(XIDETabGroupButton btn, bool hover, bool press)
        {
            Image btnV6 = XIDEPanelResource.未命名_13;
            int index = (int)btn;
            Image img = GetBtnImage(btnV6, index);


            const int SIZE = 17;
            Bitmap bitmap = new Bitmap(SIZE, SIZE);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                Color backColor = (press && hover) ? ColorHelper.Dark(m_FocusColor) : (hover ? ColorHelper.Light(m_FocusColor) : Color.Transparent);
                Color borderColor = (hover) ? ColorHelper.DarkDark(m_FocusColor) : Color.Transparent;

                g.Clear(backColor);
                g.DrawRectangle(new Pen(borderColor), new Rectangle(0, 0, SIZE - 1, SIZE - 1));
                g.DrawImage(img, 0, 0);
            }
            return bitmap;
        }
        private static Image GetBtnImage(Image imgV6, int index)
        {
            const int SIZE = 17;
            Bitmap bitmap = new Bitmap(SIZE, SIZE);
            using (Graphics g = Graphics.FromImage(bitmap))
                g.DrawImage(imgV6, new Rectangle(0, 0, SIZE, SIZE), new Rectangle(0, (index * SIZE), SIZE, SIZE), GraphicsUnit.Pixel);
            return bitmap;
        }

        #endregion




        public virtual void DoClose()
        {
            var idePanel = this.IDEPanel;
            bool suspend = (idePanel != null) && idePanel.SuspendLayout();

            var listPage = new List<DTGP>(this.m_ListPage);
            foreach (var page in listPage) { RemoveTabPage(page); }

            if (suspend) idePanel.ResumeLayout();
        }
        public virtual void DoClose(DTGP page)
        {
            var idePanel = this.IDEPanel;
            bool suspend = (idePanel != null) && idePanel.SuspendLayout();

            RemoveTabPage(page);

            if (suspend) idePanel.ResumeLayout();
        }
        public virtual void DoRivet()
        {
            var idePanel = this.IDEPanel;
            bool suspend = (idePanel != null) && idePanel.SuspendLayout();

            var state = this.State;
            if (state == DTGS.Expand || state == DTGS.Collapse || state == DTGS.Popup)
            {
                if (state == DTGS.Collapse || state == DTGS.Popup) { this.State = DTGS.Expand; this.Focus(); }
                else if (state == DTGS.Expand) { this.State = DTGS.Collapse; }
            }

            if (suspend) idePanel.ResumeLayout();
        }
        public virtual void DoNormal()
        {
            var floatForm = this.FindForm() as XIDEFloatForm;
            if (floatForm != null) floatForm.WindowState = FormWindowState.Normal;
        }
        public virtual void DoMaximize()
        {
            var floatForm = this.FindForm() as XIDEFloatForm;
            if (floatForm != null) floatForm.WindowState = FormWindowState.Maximized;
        }
        public virtual void DoMenuStrip(DTG group, DTGP page, bool rightButton)
        {
            var idePanel = this.IDEPanel;
            if (idePanel != null)
            {
                var items = idePanel.CreateTabMenuItems(this, page, rightButton);

                if (rightButton)
                {
                    var point = Win32API.GetMouseCtrlPoint(this);
                    idePanel.OpenMenuStrip(this, page, point, items);
                }
                else
                {
                    var rect = this.RectMenuStrip;
                    idePanel.OpenMenuStrip(this, page, new Point(rect.X, rect.Y + rect.Height), items);
                }
            }
        }
        public virtual void DoStateChanged()
        {
            var splitCtrl = this.ParentSplitControl;
            if (splitCtrl != null)
            {
                //splitCtrl.DoLayout();  //todo: 
                //if (m_IDEPanel != null) m_IDEPanel.ResetLayout();
            }
        }



        #region  执行 IDEFloatForm 悬浮

        protected Point m_DragTitlePoint;
        protected bool m_IsDragGroup;
        protected bool m_IsDragPage;
        protected DTGP m_DragPage;
        protected bool m_DragPageChanged;
        protected List<DTGPR> m_ListPageRectCache;

        public void StartFloat(Point point)
        {
            m_IsDragGroup = this.RectTitle.Contains(point);
            if (m_IsDragGroup)
            {
                var popupPage = this.PopupPage;
                if (this.State == DTGS.Popup && popupPage != null)
                {
                    m_DragPage = popupPage;
                    m_IsDragPage = true;
                    m_IsDragGroup = false;
                    m_DragTitlePoint = point;
                    return; 
                }
                else { m_DragPage = null; m_DragTitlePoint = point; return; }
            }

            var list = new List<XIDETabGroupPage>(m_ListPage);
            foreach (var page in list)
            {
                var rect = page.RectRealTitle;
                bool isDragPage = rect.Contains(point);
                if (isDragPage)
                {
                    var relaPoint = new Point(point.X - rect.X, point.Y - rect.Y); //point; 
                    m_DragPage = page;
                    m_IsDragPage = true; 
                    m_DragTitlePoint = relaPoint;
                    this.SetSelectedPage(page);

                    var listCache = new List<DTGPR>();
                    for(int i=0, len=list.Count;i<len;i++)
                    {
                        var page2 = list[i];
                        listCache.Add(new DTGPR(i, page2.RectRealTitle, page2));
                    }
                    m_ListPageRectCache = listCache;
                    return;
                }
            }
        }
        public void MoveFloat(Point point)
        {
            if (m_IsDragGroup)
            {
                #region  拖拽整个Group

                XIDEFloatForm floatForm = this.FindForm() as XIDEFloatForm;
                if (floatForm != null)
                {
                    #region  如果是最大化, 则将其正常化

                    if (floatForm.WindowState == FormWindowState.Maximized)
                    {
                        var rectOld = this.RectText;
                        floatForm.WindowState = FormWindowState.Normal;
                        var rectNew = this.RectText;
                        var x = (m_DragTitlePoint.X*rectNew.Width/rectOld.Width);
                        m_DragTitlePoint = new Point(x, m_DragTitlePoint.Y);
                    }

                    #endregion

                    #region  悬浮状态, 则让窗体随控件被拖动

                    int offsetX = (point.X - m_DragTitlePoint.X);
                    int offsetY = (point.Y - m_DragTitlePoint.Y);
                    floatForm.Location = new Point(floatForm.Location.X + offsetX, floatForm.Location.Y + offsetY);
                    this.Focus();

                    #endregion
                }
                else if (!RectTitle.Contains(point))
                {
                    #region  拽出标题区, 则开始进入 悬浮状态

                    //MessageBox.Show("拖出标题区范围");
                    var idePanel = this.IDEPanel;
                    int padding = XIDEFloatForm.PADDING;
                    int offsetX = (point.X - m_DragTitlePoint.X);
                    int offsetY = (point.Y - m_DragTitlePoint.Y);
                    Rectangle rect1 = this.RectangleToScreen(new Rectangle(Point.Empty, this.Size));
                    Rectangle rect2 = new Rectangle(rect1.X - padding + offsetX, rect1.Y - padding + offsetY, rect1.Width + (padding * 2), rect1.Height + (padding * 2));
                    this.Parent = null;
                    XIDEFloatForm.ShowControl(idePanel, this, rect2);
                    return;

                    #endregion
                }

                #endregion
            }
            else if (m_IsDragPage)
            {
                #region  拖拽单个Page
                
                //如果本次 Page拖拽中, 改变过 Page的Index, 则将 分离区扩大: 防止 Page交换操作 误变成 拖拽悬浮操作
                bool isPopup = (this.State == DTGS.Popup && this.PopupPage != null);
                var rectP = isPopup ? this.RectTitle : this.RectFullTabPage;
                if (m_DragPageChanged) { rectP = new Rectangle(rectP.X - 50, rectP.Y - 40, rectP.Width + 100, rectP.Height + 80); } //大范围 防止误操作
                else { rectP = new Rectangle(rectP.X - 25, rectP.Y - 20, rectP.Width + 50, rectP.Height + 40); } //小范围 防止误操作

                var page = this.m_DragPage;
                if (!rectP.Contains(point))
                {
                    #region  拽出Page分页标题区, 则开始进入 悬浮状态

                    //MessageBox.Show("拖出Page分页标题区范围");
                    var group = SeparateTabGroup(page);  //这里的 group==this
                    if (group == null) return;

                    var point2 = m_DragTitlePoint;
                    var idePanel = this.IDEPanel;
                    int padding = XIDEFloatForm.PADDING;
                    int offsetX = (point.X - m_DragTitlePoint.X);
                    int offsetY = (point.Y - m_DragTitlePoint.Y);
                    Rectangle rect1 = this.RectangleToScreen(new Rectangle(Point.Empty, this.Size));
                    Rectangle rect2 = new Rectangle(rect1.X - padding + offsetX, rect1.Y - padding + offsetY, rect1.Width + (padding * 2), rect1.Height + (padding * 2));
                    group.Parent = null;
                    EndFloat(point);
                    
                    XIDEFloatForm.ShowControl(idePanel, group, rect2);
                    group.StartFloat(point2);
                    return;

                    #endregion
                }
                else if (!isPopup)
                {
                    #region  在Page分页标题区内拖拽, 则调整Page顺序

                    var list = new List<DTGPR>(m_ListPageRectCache);
                    foreach (var rect in list)
                    {
                        if (rect.Rect.Contains(point))
                        {
                            if (rect.Page == page && !m_DragPageChanged) { continue; }
                            int index2 = rect.Index;
                            m_ListPage.Remove(page);
                            m_ListPage.Insert(index2, page);
                            m_DragPageChanged = true;
                        }
                    }
                    this.ResetRect();
                    this.Invalidate();

                    #endregion
                }

                #endregion
            }
        }
        public void EndFloat(Point point)
        {
            XIDEFloatForm floatForm = this.FindForm() as XIDEFloatForm;
            if (m_IsDragGroup && floatForm != null)
            {
                XIDEEventArgs arg = floatForm.NewIDEEventArgs();
                if (arg != null) IDEPanel.DoDock(this, arg);
                floatForm.HideTipForm();
            }

            m_DragPage = null;
            m_IsDragPage = false;
            m_IsDragGroup = false;
            m_DragPageChanged = false;
            m_ListPageRectCache = null;
            m_DragTitlePoint = Point.Empty;
        }

        #endregion


        /// <summary>
        /// 释放当前 IDETabGroup 的 所有父级变量 (包括 实际的 Parent控件, 预定附着的 Parent控件)
        /// </summary>
        public XIDETabGroup ReleaseParent()
        {
            this.Parent = null;

            var old2 = ParentSplitControl;
            m_ParentSplitPanel = null;
            if (old2 != null) { old2.DoLayout(); }

            return this;
        }
        public void DisposeOtherPopGroup()
        {
            //关闭弹出面板
            var popPanel = XIDEPopPanel.ActivePopPanel;
            if (popPanel != null && popPanel.IDETabGroup != this) { XIDEPopPanel.TogglePopGroup(null); }
        }
        public XIDETabGroup DisposeFloatForm()
        {
            XIDEPopPanel.TogglePopGroup(null);
            var floatForm = this.FindForm() as XIDEFloatForm;
            if (floatForm != null)
            {
                this.Parent = null;
                floatForm.Dispose();
            }
            return this;
        }


        public void DoLayout()
        {
            Console.WriteLine("IDEPanelGroup.DoLayout() 111111");
            var parent = this.Parent;
            //if (parent == null) return;

            //if (parent is SplitterPanel)
            //{
            //    var splitCtrl = parent.Parent as IDESplitControl;
            //    if (splitCtrl != null)
            //    {
            //        splitCtrl.ResetLayout();
            //    }
            //}
            //if (parent is IDEPanelCenter)
            //{
            //    var panelCenter = (IDEPanelCenter)parent;
            //    panelCenter.ResetLayout();
            //}
            Console.WriteLine("IDEPanelGroup.DoLayout() 222222");
        }

        public virtual new void Dispose()
        {
            if (this.Disposing || this.IsDisposed) return;
            base.Dispose();
        }




        public void Test()
        {
            //new TreeView().ExpandAll();
            //new SplitContainer().Panel1Collapsed;
        }
    }

    public class XIDETabGroupPage
    {
        private XIDEFrame m_Control = null;
        private XIDETabGroup m_ParentGroup = null;

        private string m_Text = string.Empty;
        private Size m_IconSize = Size.Empty;
        private Size m_TextSize = Size.Empty;
       
        private int m_FullWidth = 0;
        private Rectangle m_RectRealTitle = Rectangle.Empty;
        private Rectangle m_RectRealClose = Rectangle.Empty;
        private Rectangle m_RectRealIcon = Rectangle.Empty;
        private Rectangle m_RectRealText = Rectangle.Empty;


        public Image Icon
        {
            get { return m_Control == null ? null : m_Control.Icon; }
        }
        public string Text
        {
            get { return m_Control == null ? "" : m_Control.Text; }
        }
        public XIDEFrame Control
        {
            get { return m_Control; }
            set
            {
                m_Control = value;
                m_IconSize = m_TextSize = Size.Empty; 
                ResetRect();
            }
        }
        public XIDETabGroup ParentGroup
        {
            get { return m_ParentGroup; }
            set { m_ParentGroup = value; m_IconSize = m_TextSize = Size.Empty; m_FullWidth = 0; }
        }

        public Size IconSize
        {
            get
            {
                if (m_IconSize == Size.Empty)
                {
                    var icon = this.Icon;
                    m_IconSize = (icon != null) ? icon.Size : Size.Empty;
                    m_FullWidth = 0;
                }
                return m_IconSize;
            }
        }
        public Size TextSize
        {
            get
            {
                if (m_TextSize == Size.Empty)
                {
                    var dockGroup = this.ParentGroup;
                    var idePanel = dockGroup == null ? null : dockGroup.IDEPanel;
                    if (idePanel != null)
                    {
                        m_TextSize = GraphicsHelper.GetStringPixel(this.Text, idePanel.Font);
                        m_FullWidth = 0;
                    }
                }
                return m_TextSize;
            }
        }
        public int FullWidth
        {
            get
            {
                if (m_FullWidth <= 0)
                {
                    const int BTN_SIZE = DTG.CAPTION_BTN_SIZE;
                    var iconSize = this.IconSize;
                    var textSize = this.TextSize;
                    var fullWidth = textSize.Width + 6;
                    var dockGroup = this.ParentGroup;
                    
                    if (dockGroup != null && dockGroup.Alignment == XIDEAlignment.Center) fullWidth = fullWidth + BTN_SIZE + 3;
                    if (iconSize.Width >= 1) fullWidth = fullWidth + iconSize.Width + 3;
                    //if (m_FullWidth != fullWidth && m_FullWidth >= 1) Console.WriteLine("FullWidth: {0} > {1}", m_FullWidth, fullWidth);
                    m_FullWidth = fullWidth;
                }
                return m_FullWidth;
            }
        }

        public Rectangle RectRealTitle
        {
            get { return m_RectRealTitle; }
            set
            {
                m_RectRealTitle = value;
                ResetRect();
            }
        }
        public Rectangle RectRealClose
        {
            get { return m_RectRealClose; }
        }
        public Rectangle RectRealIcon
        {
            get { return m_RectRealIcon; }
        }
        public Rectangle RectRealText
        {
            get { return m_RectRealText; }
        }

        public void ResetRect()
        {
            var icon = this.Icon;
            var text = this.Text;
            var iconSize = (icon != null) ? icon.Size : Size.Empty;
            if (iconSize != m_IconSize || text != m_Text) { m_Text = text; m_IconSize = iconSize; m_TextSize = Size.Empty; m_FullWidth = 0; }


            m_RectRealClose = Rectangle.Empty;
            m_RectRealIcon = Rectangle.Empty;
            m_RectRealText = Rectangle.Empty;

            var group = ParentGroup;
            var rectTitle = RectRealTitle;
            const int BTN_SIZE = DTG.CAPTION_BTN_SIZE;

            if (rectTitle.Width >= 2)
            {
                if (group != null && group.Alignment == DA.Center)
                    m_RectRealClose = new Rectangle(rectTitle.X + rectTitle.Width - 3 - BTN_SIZE, rectTitle.Y + (rectTitle.Height - BTN_SIZE) / 2, BTN_SIZE, BTN_SIZE);

                if (group != null)
                    m_RectRealIcon = new Rectangle(rectTitle.X + 3, rectTitle.Y + (rectTitle.Height - BTN_SIZE) / 2, iconSize.Width, iconSize.Height);

                if (group != null)
                {
                    var textWidth = rectTitle.Width - 6;
                    if (m_RectRealIcon.Width >= 1) textWidth = textWidth - m_RectRealIcon.Width - 3;
                    if (m_RectRealClose.Width >= 1) textWidth = textWidth - m_RectRealClose.Width - 3;
                    m_RectRealText = new Rectangle(m_RectRealIcon.X + m_RectRealIcon.Width + 1, rectTitle.Y + (rectTitle.Height - m_TextSize.Height) / 2, textWidth, m_TextSize.Height);
                }
            }
        }
    }

    public class XIDETabGroupPageRect
    {
        public XIDETabGroupPageRect(int index, Rectangle rect, XIDETabGroupPage page)
        {
            this.Index = index;
            this.Rect = rect;
            this.Page = page;
        }

        public int Index{get;set;}
        public Rectangle Rect{get;set;}
        public XIDETabGroupPage Page{get;set;}
    }


    public class XIDEMenuItemInfo
    {
        public XIDEMenuItemInfo(XIDETabGroup group, XIDETabGroupPage page, XIDEMenuItem item)
        {
            this.Group = group;
            this.Page = page;
            this.Item = item;
        }

        public XIDETabGroup Group { get; set; }
        public XIDETabGroupPage Page { get; set; }
        public XIDEMenuItem Item { get; set; }
    }
    public class XIDEMenuItem
    {
        public XIDEMenuItem(string name, string text, bool enabled, object tag)
        {
            this.Name = name;
            this.Text = text;
            this.Enabled = enabled;
            this.Tag = tag;
        }
        public XIDEMenuItem(string name, string text,bool enabled) : this(name, text, enabled, null)
        {
        }
        public XIDEMenuItem(string name, string text) : this(name, text, true, null)
        {
        }

        public string Name { get; set; }
        public string Text { get; set; }
        public Image Icon { get; set; }
        public bool Enabled { get; set; }
        public object Tag { get; set; }
    }


    [Serializable]
    public enum XIDETabGroupState
    {
        Expand,
        Collapse,
        Popup,
        Float,
        Hide,
        Dispose,
    }

    [Serializable]
    public enum XIDETabGroupButton
    {
        Menu = 0,
        Expand = 1,
        Collapse = 2,
        Maximize = 3,
        Normal = 4,
        Close = 5,
    }



    public class XIDEPageEventArgs : EventArgs
    {
        public DTGP Page { get; set; }
        public XIDEPageEventArgs(DTGP page) { this.Page = page; }
    }
    public class XIDEMenuStripEventArgs : EventArgs
    {
        public DTG Group { get; set; }
        public DTGP Page { get; set; }
        public bool RightButton { get; set; }
        public XIDEMenuStripEventArgs(DTG group, DTGP page, bool rightButton) { this.Group = group; this.Page = page; this.RightButton = rightButton; }
    }
    public delegate void XIDEPageEventHandler(object sender, XIDEPageEventArgs e);
    public delegate void XIDEMenuStripEventHandler(object sender, XIDEMenuStripEventArgs e);

}
